#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
from log.logger import create_logger
create_logger('variables', '/var/log/kellan/config')
from conf.yaml_tool import yaml_load, yaml_dump
from pg.region import get_region_vars
from pg.zone import get_zone_ids, get_zone_vars
from conf.jinja2_tool import jinja2_dump
from k8s.env import CONF_DIR, TEMPLATES_DIR
from kubernetes import client, config
from log.logger import logger
import json
from pg import region as pg_region
from pg import zone as pg_zone
from misc.color import INFO, SINFO, CRIT, SUMM, WARN
import commands

# 在CONF_DIR定义的目录下生成zone_id/cm/zonevar.yaml文件
def gen_config_map_zone_var(zone_id):
    msg = "Building yaml for configmap [zonevar], namespace: [%s] ..." % zone_id
    logger.info(msg)
    print(INFO % ("|--Info: " + msg))
    configuration = {}
    configuration['name'] = 'zonevar'
    configuration['zone_id'] = zone_id
    configuration['variables'] = formater(get_zone_vars(zone_id))
    config_map_path = os.path.join(CONF_DIR, "%s/cm/zonevar.yaml"%zone_id)
    if not os.path.exists(os.path.join(TEMPLATES_DIR, "cm_vars.yaml.j2")):
        msg = "Template file for variables configmap does not exists: [%s]" % os.path.join(TEMPLATES_DIR, "cm_vars.yaml.j2")
        logger.error(msg)
        print(CRIT % ("|--Error: " + msg))
        return
    jinja2_dump(TEMPLATES_DIR, "cm_vars.yaml.j2", configuration, config_map_path)

# 在CONF_DIR定义的目录下生成zone_id/cm/regionvar.yaml文件
def gen_config_map_region_var(zone_id):
    msg = "Building yaml for configmap [regionvar], namespace: [%s] ..." % zone_id
    logger.info(msg)
    print(INFO % ("|--Info: " + msg))

    from pg import zone as pg_zone
    zone_ids = pg_region.get_zone_ids()
    configuration = {}
    configuration['name'] = 'regionvar'
    configuration['variables'] = formater(get_region_vars())
    # 生成region的large_mgmt_networks
    large_mgmt_networks = []
    for zone in zone_ids:
        large_mgmt_networks.extend(pg_zone.get_large_mgmt_networks(zone))
    large_mgmt_networks = ' '.join(list(set(large_mgmt_networks)))
    configuration['variables']['large_mgmt_networks'] = '"%s"' % large_mgmt_networks
    # 生成configmap的yaml
    config_map_path = os.path.join(CONF_DIR, "%s/cm/regionvar.yaml"%zone_id)
    if not os.path.exists(os.path.join(TEMPLATES_DIR, "cm_vars.yaml.j2")):
        msg = "Template file for variables configmap does not exists: [%s]" % os.path.join(TEMPLATES_DIR, "cm_vars.yaml.j2")
        logger.error(msg)
        print(CRIT % ("|--Error: " + msg))
        return
    jinja2_dump(TEMPLATES_DIR, "cm_vars.yaml.j2", configuration, config_map_path)


def formater(vars):
    for k in vars:
        vars[k] ='"%s"' % vars[k]
    return vars


class CMClient(object):
    def __init__(self, namespace):
        from log.logger import logger
        self.logger = logger
        self.namespace = namespace
        self.ctx = client.CoreV1Api()

    def create(self, component):
        msg = "Namespace [%s]: creating Configmap [%s]" % (self.namespace, component)
        self.logger.info(msg)
        print(SINFO % ("|--Info: " + msg))

        if component in ['zonevar', 'regionvar']:
            yaml_file = os.path.join(CONF_DIR, "%s/cm/%s.yaml" % (self.namespace, component))
        else:
            yaml_file = os.path.join(CONF_DIR, "%s/%s/cm.yaml" % (self.namespace, component))

        if os.path.getsize(yaml_file) == 0:
            msg = "skip empty file %s" % yaml_file
            self.logger.error(msg)
            print(WARN % ("  |--Warn: " + msg))
            return

        bodies = yaml_load(yaml_file, all=True)
        if not bodies:
            msg = "failed to load content from %s" % yaml_file
            self.logger.error(msg)
            print(CRIT % ("  |--Error: " + msg))
            return

        for body in bodies:
            try:
                resp = self.ctx.create_namespaced_config_map(body=body, namespace=self.namespace)
                msg = "Namespace [%s]: ConfigMap created. name='%s'" % (self.namespace, resp.metadata.name)
                self.logger.info(msg)
                print(INFO % ("  |--Info: " + msg))
            except Exception as e:
                # conflict exception: 409
                if str(e).split()[0] != '(409)':
                    msg = str(e)
                    print(CRIT % ("  |--Error: " + msg))
                else:
                    msg = "instance already exits."
                    print(INFO % ("  |--Info: " + msg))
                self.logger.critical(msg)

    def patch(self, name, data):
        body = {
            "data": data
        }
        self.ctx.patch_namespaced_config_map(namespace=self.namespace, name=name, body=body)

    def delete(self, name):
        try:
            resp = self.ctx.delete_namespaced_config_map(name=name, namespace=self.namespace)
            print("ConfigMap deleted. name='%s'" % resp.metadata.name)
            self.logger.info("ConfigMap deleted. name='%s'" % resp.metadata.name)
        except Exception as e:
            print(e)
            self.logger.critical(e)

    def update(self, component):
        if component in ['zonevar', 'regionvar']:
            yaml_file = os.path.join(CONF_DIR, "%s/cm/%s.yaml" % (self.namespace, component))
        else:
            yaml_file = os.path.join(CONF_DIR, "%s/%s/cm.yaml" % (self.namespace, component))

        msg = "Namespace [%s]: updating ConfigMap [%s]" % (self.namespace, component)
        self.logger.info(msg)
        print(SINFO % ("|--Info: " + msg))
        status, msg = commands.getstatusoutput("export KUBECONFIG=/root/.kube/config; kubectl -n %s apply -f %s" % (self.namespace, yaml_file))
        if status == 0:
            self.logger.info(msg)
            print(INFO % ("  |--Info: " + msg))
        else:
            self.logger.error(msg)
            print(CRIT % ("  |--Error: " + msg))

    def get(self, name):
        cm = json.loads(self.ctx.list_namespaced_config_map(
            namespace=self.namespace,
            _preload_content=False,
            field_selector="metadata.name=%s"%name).read())
        return cm['items'][0]
